﻿using Pay.Core;
using Pay.Data;
using Pay.DTO;
using Pay.IService;
using Pay.Service.Cache;
using Pay.TO;
using System;
using System.Collections.Generic;
using System.Data.Entity.SqlServer;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Pay.Service {
    public class TokenTransferService : MerchantBillService, ITokenTransferService, IDisposable {
        private IUnitOfWork _iUnitOfWork;
        private IRedRecordService _iRedRecordService;
        private ITokenStatisticsService _iTokenStatisticsService;
        private IMerchantBankCardService _iMerchantBankCardService;
        private static readonly object tokenLock = new object();
        /// <summary>
        /// 
        /// </summary>
        /// <param name="iUnitOfWork"></param>
        /// <param name="iMerchantService"></param>
        /// <param name="_RedRecordService"></param>
        /// <param name="iTokenStatisticsService"></param>
        /// <param name="iBillService"></param>
        /// <param name="iSettingService"></param>
        /// <param name="iPaymentService"></param>
        /// <param name="iPayHtmlService"></param>
        /// <param name="iPayNotifyService"></param>
        /// <param name="iMerchantBankCardService"></param>
        public TokenTransferService(IUnitOfWork iUnitOfWork, IMerchantService iMerchantService,
                                    IRedRecordService _RedRecordService, ITokenStatisticsService iTokenStatisticsService,
                                    IBillService iBillService, ISettingService iSettingService, IPaymentService iPaymentService,
                                    IPayHtmlService iPayHtmlService, IPayNotifyService iPayNotifyService,
                                    IMerchantBankCardService iMerchantBankCardService)
            : base(iUnitOfWork, iSettingService, iBillService, iMerchantService, iPaymentService, iPayHtmlService, iPayNotifyService) {
            _iUnitOfWork = iUnitOfWork;
            _iMerchantService = iMerchantService;
            _iRedRecordService = _RedRecordService;
            _iBillService = iBillService;
            _iTokenStatisticsService = iTokenStatisticsService;
            _iMerchantBankCardService = iMerchantBankCardService;
        }
        public PagedResult<token_transfer_dto> Gets(TokenTansferQuery query) {
            var filter = PredicateBuilder.True<TokenTransfer>();
            if (!string.IsNullOrEmpty(query.name))
                filter = filter.And(c => c.AccountName.Contains(query.name) || c.Merchant.Mobile.Contains(query.name));
            if (query.start_time.HasValue) {
                long startTime = query.start_time.Value.ToUnix();
                filter = filter.And(c => c.ApplyTime >= startTime);
            }
            if (query.end_time.HasValue) {
                long endTime = query.end_time.Value.AddDays(1).ToUnix();
                filter = filter.And(c => c.ApplyTime <= endTime);
            }
            if (query.status.HasValue) {
                filter = filter.And(c => c.Status == (TokenTransferStatus)query.status.Value);
            }
            if (query.type.HasValue) {
                if (query.type == 1) {
                    filter = filter.And(c => c.Status == TokenTransferStatus.Auditing || c.Status == TokenTransferStatus.Fail || c.Status == TokenTransferStatus.PassedUnpaid);
                } else if (query.type == 2) {
                    filter = filter.And(c => c.Status == TokenTransferStatus.Passedpaid || c.Status == TokenTransferStatus.PayOffFail || c.Status == TokenTransferStatus.Process || c.Status == TokenTransferStatus.PassedUnpaid);
                }
            }
            return context.TokenTransfer.FromCachePaged<TokenTransfer, token_transfer_dto>(query.page, query.size, filter, orderBy => orderBy.OrderBy(c => c.Status).OrderByDescending(c => c.ApplyTime));
        }
        public token_transfer_dto Get(long id) {
            return context.TokenTransfer.FindById(id).ToDtoObject<token_transfer_dto>();
        }

        /// <summary>
        /// 提现审核详情
        /// </summary>
        /// <param name="id"></param>
        /// <param name="queryPage"></param>
        /// <returns></returns>
        public token_transfer_dto_ex GetDetail(long id, PageQuery queryPage) {
            token_transfer_dto_ex result = new token_transfer_dto_ex();
            Get(id).ToCopyProperty(result);
            if (result.transfer_type == TokenTransferType.Distribution || result.transfer_type == TokenTransferType.Shop) {//分销收益、店铺收益
                var q = context.Profits.Where(o => o.MerchantId == result.merchant_id && o.BillStatus == BillStatus.Finish); // context.BillDetails.Where(o => o.Bill.MerchantId == result.merchant_id && o.Status != BillStatus.Cancel);
                if (result.transfer_type == TokenTransferType.Distribution)//分销收益
                    q = q.Where(o => o.BillType == BillType.Distribution && !o.IsBus);
                else if (result.transfer_type == TokenTransferType.Shop)//店铺收益
                    q = q.Where(o => o.BillType == BillType.Mall);
                var rowsCount = q.Count();
                var rows = (q.OrderByDescending(o => o.CreateTime).Skip((queryPage.page - 1) * queryPage.size).Take(queryPage.size).ToList() ?? new List<Profit>())
                    .Select(o => new token_transfer_commission_detail() {
                        pay_id = o.PayId,
                        buyer_mobile = (o.Order != null && o.Order.Buyer != null)
                                        ? o.Order.Buyer.Mobile : "",
                        buyer_name = (o.Order != null && o.Order.Buyer != null)
                                        ? o.Order.Buyer.Name : "",
                        commission = o.Amount,
                        create_time = o.CreateTime.ToDateTime(),
                        remark = ""
                    }).ToList();
                result.token_transfer_commission_list = new PagedResult<token_transfer_commission_detail>(rows, rowsCount, queryPage.page, queryPage.size);
                if (rowsCount > 0) {
                    result.total_commission = q.Sum(o => o.Amount);
                    var deposit = context.TokenTransfer.Where(c => c.MerchantId == result.merchant_id && c.Status == TokenTransferStatus.PassedUnpaid && (c.TransferType == TokenTransferType.Distribution || c.TransferType == TokenTransferType.Shop)).Sum(c => (decimal?)c.TransferAmount);
                    result.depositing = deposit ?? 0;
                }

            } else if (result.transfer_type == TokenTransferType.Upgrade || result.transfer_type == TokenTransferType.Bus) {//课程收益、业绩收益
                var q1 = context.Profits.Where(o => o.MerchantId == result.merchant_id && o.BillStatus == BillStatus.Finish);
                if (result.transfer_type == TokenTransferType.Upgrade)//课程收益
                    q1 = q1.Where(o => o.BillType == BillType.Distribution && o.TokenBillType == TokenBillType.MarkBill);
                else if (result.transfer_type == TokenTransferType.Bus)//业绩收益
                    q1 = q1.Where(o => o.BillType == BillType.Distribution && o.IsBus);
                var rowsCount1 = q1.Count();
                var rows1 = (q1.OrderByDescending(o => o.CreateTime).Skip((queryPage.page - 1) * queryPage.size).Take(queryPage.size).ToList() ?? new List<Profit>())
                    .Select(o => new token_transfer_commission_detail() {
                        pay_id = o.PayId,
                        buyer_mobile = result.transfer_type == TokenTransferType.Upgrade ? (o.Amount > 0 && o.Order != null && o.Order.Buyer != null) ? o.Order.Buyer.Mobile : "" : "",
                        buyer_name = result.transfer_type == TokenTransferType.Upgrade ? (o.Amount > 0 && o.Order != null && o.Order.Buyer != null) ? o.Order.Buyer.Name : "" : "",
                        commission = o.Amount,
                        create_time = o.CreateTime.ToDateTime(),
                        remark = ""
                    }).ToList();

                if (rows1 != null && rows1.Count() > 0 && result.transfer_type == TokenTransferType.Bus) {
                    foreach (var row in rows1) {
                        if (row.pay_id != null) {
                            var payInfo = context.PayInfos.Where(o => o.Id == row.pay_id).FirstOrDefault();
                            if (payInfo != null && payInfo.Orders != null && payInfo.Orders.FirstOrDefault() != null && payInfo.Orders.FirstOrDefault().Buyer != null) {
                                row.buyer_mobile = payInfo.Orders.FirstOrDefault().Buyer.Mobile;
                                row.buyer_name = payInfo.Orders.FirstOrDefault().Buyer.Name;
                            }
                        }
                    }
                }
                result.token_transfer_commission_list = new PagedResult<token_transfer_commission_detail>(rows1, rowsCount1, queryPage.page, queryPage.size);
                if (rowsCount1 > 0) {
                    result.total_commission = q1.Sum(o => o.Amount);
                    var deposit = context.TokenTransfer.Where(c => c.MerchantId == result.merchant_id && c.Status == TokenTransferStatus.PassedUnpaid && c.TransferType == TokenTransferType.Upgrade).Sum(c => (decimal?)c.TransferAmount);
                    result.depositing = deposit ?? 0;
                }
            }
            return result;
        }

        /// <summary>
        /// 提现审核
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool Audit(token_transfer_model model) {
            var transfer = context.TokenTransfer.FindById(model.id);
            if (transfer.Status != TokenTransferStatus.Auditing) { throw new ServerErrorException("只有在待审核状态才能审核"); }
            var transfer_status = (TokenTransferStatus)model.status;
            if (transfer_status == TokenTransferStatus.Auditing) {
                transfer.Remark = model.remark;
            } else if (transfer_status == TokenTransferStatus.Fail) {
                transfer.Status = TokenTransferStatus.Fail;
                TokenTransferRefund(transfer);
            } else {
                transfer.Status = (TokenTransferStatus)model.status;
                transfer.Remark = model.remark;
            }
            transfer.AuditTime = DateTime.Now.ToUnix();
            transfer.AuditManageId = model.manager_id;
            return _iUnitOfWork.Commit() > 0;
        }
        /// <summary>
        /// 修改银行卡
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool UpdateBank(token_tranfer_bank_model model) {
            var transfer = context.TokenTransfer.FindById(model.id);
            transfer.AccountName = model.account_name;
            transfer.AccountNo = model.account_name;
            transfer.BankName = model.bank_name;
            transfer.BranchAddress = model.branch_address;
            return _iUnitOfWork.Commit() > 0;
        }
        /// <summary>
        /// token 钱包
        /// </summary>
        /// <returns></returns>
        public List<token_wallet_dto> GetWallet(long merchantId) {
            var merchant = _iMerchantService.Get(merchantId);
            string url = t_RequestMethod.token_url;
            List<token_wallet_dto> wallet = new List<token_wallet_dto>();
            //红钻
            token_wallet_dto red_wallet = new token_wallet_dto();
            var redRecord = _iRedRecordService.GetUser(merchantId);
            red_wallet.backgroud_img = string.Format("{0}/Content/images/wallet/bg_h.png", url);
            red_wallet.icon = string.Format("{0}/Content/images/wallet/icon_h.png", url);
            red_wallet.value = redRecord.present_red_drill.ToString("f6");
            red_wallet.type = TokenTransferType.None;
            red_wallet.type_desc = TokenTransferType.None.ToDescription();
            red_wallet.unit = "个";
            wallet.Add(red_wallet);
            //分销
            var bill = _iBillService.GetByMerchant(merchantId);
            token_wallet_dto distribution_wallet = new token_wallet_dto();
            distribution_wallet.backgroud_img = string.Format("{0}/Content/images/wallet/bg_huang.png", url);
            distribution_wallet.icon = string.Format("{0}/Content/images/wallet/icon_huang.png", url);
            distribution_wallet.value = (bill.unconfirmed + bill.deposit + bill.depositeding).ToString("f2");
            distribution_wallet.type = TokenTransferType.Distribution;
            distribution_wallet.type_desc = TokenTransferType.Distribution.ToDescription();
            distribution_wallet.unit = "元";
            wallet.Add(distribution_wallet);
            //课程
            if (merchant.usertype >= UserType.tokenMaker) {
                token_wallet_dto upgrade_wallet = new token_wallet_dto();
                var token_staitic = _iTokenStatisticsService.GetOrCreate(merchantId);
                upgrade_wallet.backgroud_img = string.Format("{0}/Content/images/wallet/bg_l.png", url);
                upgrade_wallet.icon = string.Format("{0}/Content/images/wallet/icon_l.png", url);
                upgrade_wallet.value = (token_staitic.deposit + token_staitic.frozen_profit).ToString("f2");
                upgrade_wallet.type = TokenTransferType.Upgrade;
                upgrade_wallet.type_desc = TokenTransferType.Upgrade.ToDescription();
                upgrade_wallet.unit = "元";
                wallet.Add(upgrade_wallet);
            }
            //店铺
            if (merchant.usertype >= UserType.tokenNodeMall) {
                token_wallet_dto shop_wallet = new token_wallet_dto();
                shop_wallet.backgroud_img = string.Format("{0}/Content/images/wallet/bg_z.png", url);
                shop_wallet.icon = string.Format("{0}/Content/images/wallet/icon_z.png", url);
                shop_wallet.value = (bill.goods_unconfirmed + bill.goods_deposit + bill.goods_depositing).ToString("f2");
                shop_wallet.type = TokenTransferType.Shop;
                shop_wallet.type_desc = TokenTransferType.Shop.ToDescription();
                shop_wallet.unit = "元";
                wallet.Add(shop_wallet);
            }
            return wallet;
        }
        /// <summary>
        /// token 钱包收益详情
        /// </summary>
        /// <param name="mechantId"></param>
        /// <param name="type">1 分销 2 课程 3 店铺</param>
        /// <returns></returns>
        public token_wallet_detail_dto GetWalletDetail(long mechantId, int type) {
            token_wallet_detail_dto wallet = new token_wallet_detail_dto();
            if (type == 2) {
                var token_staitic = _iTokenStatisticsService.GetOrCreate(mechantId);
                wallet.deposit = token_staitic.deposit.ToString("f2");
                //冻结= 提现中 + 待冻结
                wallet.deposting = (token_staitic.depositing + token_staitic.frozen_profit).ToString("f2");
                //总金额= 提现+提现中+待冻结
                wallet.money = (token_staitic.deposit + token_staitic.depositing + token_staitic.frozen_profit).ToString("f2");
            } else {
                var bill = _iBillService.GetByMerchant(mechantId);
                if (type == 1) {
                    wallet.deposit = bill.deposit.ToString("f2");
                    wallet.deposting = (bill.depositeding + bill.unconfirmed).ToString("f2");
                    wallet.money = (bill.unconfirmed + bill.deposit + bill.depositeding).ToString("f2");
                } else if (type == 3) {
                    wallet.deposit = bill.goods_deposit.ToString("f2");
                    wallet.deposting = (bill.goods_unconfirmed + bill.goods_depositing).ToString("f2");
                    wallet.money = (bill.goods_unconfirmed + bill.goods_deposit + bill.goods_depositing).ToString("f2");
                }
            }
            wallet.merchant_id = mechantId;
            return wallet;
        }
        /// <summary>
        /// 获取提现记录
        /// </summary>
        /// <param name="merchant_no"></param>
        /// <param name="pay_no"></param>
        /// <returns></returns>
        public token_transfer_dto GetByPayNo(string merchant_no, string pay_no) {
            return context.TokenTransfer.Where(c => c.Merchant.MerchantNo == merchant_no && c.PayInfo.PayNo == pay_no).FirstOrDefault().ToDtoObject<token_transfer_dto>();
        }
        public token_transfer_dto Get(string merchant_no, string order_no) {
            return context.TokenTransfer.FirstOrDefault(c => c.OrderNo == order_no && c.Merchant.MerchantNo == merchant_no).ToDtoObject<token_transfer_dto>();
        }
        /// <summary>
        /// 申请提现记录
        /// </summary>
        /// <param name="merchant_id"></param>
        /// <param name="type">类型1：分销，2：课程，3：货款，4：业绩</param>
        /// <param name="amount"></param>
        /// <returns></returns>
        public int ApplyTokenTransfer(long merchant_id, int type, decimal amount) {
            var setting = _iSettingService.GetTokenSetting().token_base_setting;
            if (setting.min_withdraw <= 0 || setting.settle_amount <= 0)
                throw new ServerErrorException("未设置提现配置");
            if (amount < setting.min_withdraw)
                throw new ServerErrorException(string.Format("提现金额不能低于￥{0}", setting.min_withdraw));
            if (amount > setting.max_withdraw)
                throw new ServerErrorException(string.Format("提现金额不能大于¥{0}", setting.max_withdraw));
            var merchant = _iMerchantService.Get(merchant_id);
            if (merchant == null || merchant.disabled)
                throw new ServerErrorException("该账号已被禁用");
            var bill = _iBillService.GetByMerchant(merchant_id);
            if (bill == null || bill.freeze)
                throw new ServerErrorException("该账号已冻结");
            decimal total = 0;
            string startTime = string.Format("{0} 00:00:00", DateTime.Now.ToString("yyyy-MM-dd"));
            string endTime = string.Format("{0} 23:59:59", DateTime.Now.ToString("yyyy-MM-dd"));
            long sTime = DateTime.Parse(startTime).ToUnix();
            long eTime = DateTime.Parse(endTime).ToUnix();
            bool has_transfer = context.TokenTransfer.Any(c => c.MerchantId == merchant_id && c.Status != TokenTransferStatus.Fail && c.ApplyTime >= sTime && c.ApplyTime <= eTime);
            if (has_transfer) {
                var transfer = context.TokenTransfer.Where(c => c.MerchantId == merchant_id && c.Status != TokenTransferStatus.Fail && c.ApplyTime >= sTime && c.ApplyTime <= eTime);
                total = transfer.Sum(c => c.TransferAmount);
            }
            if (total + amount > setting.day_withdraw)
                throw new ServerErrorException(string.Format("今日提现额度已达上限￥{0}", setting.day_withdraw));
            if (type == 1) {
                if (amount > bill.deposit)
                    throw new ServerErrorException("余额不足");
            } else if (type == 2) {
                var statistics = context.TokenStatistics.FirstOrDefault(c => c.MerchantId == merchant_id);
                if (statistics == null || (statistics.Deposit.HasValue && amount > statistics.Deposit.Value))
                    throw new ServerErrorException("余额不足");
            } else if (type == 3) {
                if (amount > bill.goods_deposit)
                    throw new ServerErrorException("余额不足");
            } else if (type == 4) {
                var statistics = context.TokenStatistics.FirstOrDefault(c => c.MerchantId == merchant_id);
                if (statistics == null || amount > statistics.BusDeposit)
                    throw new ServerErrorException("余额不足");
            }

            var card = context.MerchantBankCard.FirstOrDefault(c => c.MerchantId == merchant_id);
            if (card == null)
                throw new ServerErrorException("该账号未绑定银行卡");
            if (card.Status == EMerchantBankCardStatus.AuditFail || card.Status == EMerchantBankCardStatus.ToAudit)
                throw new ServerErrorException("银行卡审核未通过");
            //增加提现单
            var model = AddTransfer(merchant_id, amount, setting.settle_amount, type, card);
            //提现账单
            TokenTransferAccount(model);
            int result = _iUnitOfWork.Commit();
            return result;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="merchant_id"></param>
        /// <param name="amount"></param>
        /// <param name="settle_fee"></param>
        /// <param name="type">类型1：分销，2：课程，3：店铺</param>
        /// <param name="card"></param>
        /// <returns></returns>
        private TokenTransfer AddTransfer(long merchant_id, decimal amount, decimal settle_fee, int type, MerchantBankCard card) {
            var model = new TokenTransfer();
            model.MerchantId = merchant_id;
            model.TransferAmount = amount;
            model.SettleAmount = settle_fee;
            model.Amount = amount - settle_fee;
            model.AccountName = card.AccountName;
            model.AccountNo = card.AccountNum;
            model.BankName = card.BankName;
            model.BranchAddress = card.BranchName;
            model.ApplyTime = DateTime.Now.ToUnix();
            model.OrderNo = string.Format("T{0}", DtoHelper.GenerateOrderNumber());
            model.Status = TokenTransferStatus.Auditing;
            model.PayInfo = new PayInfo {
                OrderNo = model.OrderNo,
                SettleType = "T0",
                PayNo = model.OrderNo,
                PayName = "ChPay代付",
                PayChannel = PayChannel.ChPay,
                PayCode = "PAYOFF",
                PayType = PayType.Payoff,
                CreateTime = model.ApplyTime
            };
            if (type == 1)
                model.TransferType = TokenTransferType.Distribution;
            else if (type == 2)
                model.TransferType = TokenTransferType.Upgrade;
            else if (type == 3)
                model.TransferType = TokenTransferType.Shop;
            context.TokenTransfer.Add(model);
            return model;
        }
        /// <summary>
        /// 后台下发操作
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public int ReTokenTransfer(platform_transfer dto) {
            var model = context.TokenTransfer.FirstOrDefault(c => dto.order_no == c.OrderNo && c.Merchant.MerchantNo == dto.merchant_no);
            if (model.Status == TokenTransferStatus.Passedpaid)
                throw new ServerErrorException("提现单" + dto.order_no + "非提现失败或不确定状态时", 1002);
            var card = context.MerchantBankCard.FirstOrDefault(c => c.MerchantId == model.MerchantId);
            model.AccountNo = card.AccountNum;
            model.AccountName = card.AccountName;
            model.BankName = card.BankName;
            model.PayInfo.PayNo = dto.pay_no;
            if (dto.status == TransferStatus.Fail) {
                model.Status = TokenTransferStatus.Fail;
                model.Msg = dto.fail;
                TokenTransferRefund(model);
                //保存消息
                var replyMessage = new MessagePush();
                replyMessage.MerchantId = model.MerchantId;
                if (model.TransferType == TokenTransferType.Distribution)
                    replyMessage.Type = MsgType.TransferProftFail;
                else if (model.TransferType == TokenTransferType.Upgrade)
                    replyMessage.Type = MsgType.TransferOld398Fail;
                else if (model.TransferType == TokenTransferType.Shop)
                    replyMessage.Type = MsgType.TransferShopFail;
                else
                    replyMessage.Type = MsgType.Marketing;
                replyMessage.Title = "提现失败通知";
                replyMessage.ShortContent = string.Format("您的一笔{0}提现失败！", model.Amount.ToString("c"));
                replyMessage.Content = string.Format("您的一笔{0}提现失败，{1}！请重新绑定正确的实名认证时姓名和身份证的银行卡，谢谢", model.Amount.ToString("c"), dto.fail);
                replyMessage.Ext = "{}";
                replyMessage.CreateTime = DateTime.Now.ToUnix();
                replyMessage.ObjectId = model.Id;
                context.MessagePushs.Add(replyMessage);

                //发送消息
                try {
                    JPushHelp jPushHelp = new JPushHelp(t_RequestMethod.push_app_key, t_RequestMethod.push_app_secret);
                    jPushHelp.Push(replyMessage.Title, replyMessage.Content, (int)replyMessage.Type, replyMessage.ObjectId.Value, new List<string> { model.Merchant.Mobile });
                }
                catch (Exception) { }
            } else if (dto.status == TransferStatus.Proceed) {
                model.Status = TokenTransferStatus.Process;
            }
            int result = _iUnitOfWork.Commit();
            return result;
        }

        public int TransferSuccess(platform_transfer transfer) {
            lock (tokenLock) {
                var model = context.TokenTransfer.FirstOrDefault(c => transfer.order_no == c.OrderNo && c.Merchant.MerchantNo == transfer.merchant_no);
                if (model.Status == TokenTransferStatus.Passedpaid)
                    throw new ServerErrorException("提现单" + transfer.order_no + "已完成", 1002);
                model.PayInfo.TransactionNo = transfer.transaction_no;
                model.PayInfo.PayTime = transfer.pay_time.ToUnix();
                model.Status = TokenTransferStatus.Passedpaid;
                if (transfer.status == TransferStatus.Finish) {
                    if (model.TransferType == TokenTransferType.Upgrade || model.TransferType == TokenTransferType.Bus) {
                        TokenTransferAccounted(model);
                    } else {
                        TokenTransferAccounted(model, transfer.transfer_type);
                    }

                    var dtTime = DateTime.Now.ToUnix();
                    //生成负的账单明细
                    if (model.TransferType == TokenTransferType.Upgrade) {
                        context.TokenBillDetail.Add(new TokenBillDetail {
                            BillType = (model.TransferType == TokenTransferType.Upgrade ? TokenBillType.OldMarkBillTransfer : TokenBillType.DistributionTransfer),
                            Commission = -model.TransferAmount,
                            IsComfirm = true,
                            InviteMerchantId = model.MerchantId,
                            MerchantId = model.MerchantId,
                            Remark = "提现",
                            UserType = UserType.tokenMaker,
                            ReceivablesInfo = "",
                            CreateTime = dtTime
                        });
                    }
                    //保存消息
                    var replyMessage = new MessagePush();
                    replyMessage.MerchantId = model.MerchantId;
                    if (model.TransferType == TokenTransferType.Distribution)
                        replyMessage.Type = MsgType.TransferProftOK;
                    else if (model.TransferType == TokenTransferType.Upgrade)
                        replyMessage.Type = MsgType.TransferOld398OK;
                    else if (model.TransferType == TokenTransferType.Shop)
                        replyMessage.Type = MsgType.TransferShopOK;
                    else
                        replyMessage.Type = MsgType.Marketing;
                    replyMessage.Title = "提现审核通过";
                    replyMessage.ShortContent = string.Format("您的一笔{0}提现已成功，请您查收，到账时间以银行结算准！", model.Amount.ToString("c"));
                    replyMessage.Content = string.Format("您的一笔{0}提现已成功，请您查收，到账时间以银行结算准！", model.Amount.ToString("c"));
                    replyMessage.Ext = "{}";
                    replyMessage.CreateTime = DateTime.Now.ToUnix();
                    replyMessage.ObjectId = model.Id;
                    context.MessagePushs.Add(replyMessage);

                    //发送消息
                    try {
                        JPushHelp jPushHelp = new JPushHelp(t_RequestMethod.push_app_key, t_RequestMethod.push_app_secret);
                        jPushHelp.Push(replyMessage.Title, replyMessage.Content, (int)replyMessage.Type, replyMessage.ObjectId.Value, new List<string> { model.Merchant.Mobile });
                    }
                    catch (Exception) { }
                }
                int result = _iUnitOfWork.Commit();
                return result;
            }
        }

        /// <summary>
        /// 手动输入付款单号
        /// </summary>
        /// <param name="id"></param>
        /// <param name="transaction_no"></param>
        /// <returns></returns>
        public int UpdateEx(long id, string transaction_no) {
            var model = context.TokenTransfer.FirstOrDefault(c => c.Id == id);
            model.PayInfo.TransactionNo = transaction_no;
            if (model.PayInfo.CreateTime == 0) model.PayInfo.CreateTime = model.PayInfo.PayTime.HasValue ? model.PayInfo.PayTime.Value : DateTime.Now.ToUnix();
            model.Remark = "微信付款";
            int result = _iUnitOfWork.Commit();
            return result;
        }

        public int TransferFail(platform_transfer dto) {
            var model = context.TokenTransfer.FirstOrDefault(c => dto.order_no == c.OrderNo && c.Merchant.MerchantNo == dto.merchant_no);
            if (model.Status == TokenTransferStatus.Passedpaid)
                throw new ServerErrorException(dto.order_no + "提现非申请状态", 1002);
            model.Status = TokenTransferStatus.PayOffFail;
            model.PayInfo.TransactionNo = dto.transaction_no;
            model.Msg = dto.fail;
            TokenTransferRefund(model);
            int result = _iUnitOfWork.Commit();
            return result;
        }

        public PagedResult<token_deposited_dto> GetDeposited(WalletQuery query) {
            var filter = PredicateBuilder.True<TokenTransfer>();
            filter = filter.And(c => c.MerchantId == query.merchant_id);
            if (query.type == 1)
                filter = filter.And(c => c.TransferType == TokenTransferType.Distribution);
            else if (query.type == 2)
                filter = filter.And(c => c.TransferType == TokenTransferType.Upgrade);
            else if (query.type == 3)
                filter = filter.And(c => c.TransferType == TokenTransferType.Shop);
            else if (query.type == 4)
                filter = filter.And(c => c.TransferType == TokenTransferType.Bus);

            if (!string.IsNullOrEmpty(query.amount)) {
                decimal value = decimal.Parse(query.amount);
                filter = filter.And(c => c.TransferAmount == value);
            }
            if (!string.IsNullOrEmpty(query.start_time)) {
                var value = DateTime.Parse(query.start_time).ToUnix();
                filter = filter.And(c => c.ApplyTime >= value);
            }
            if (!string.IsNullOrEmpty(query.end_time)) {
                var value = DateTime.Parse(query.end_time).ToUnix();
                filter = filter.And(c => c.ApplyTime <= value);
            }
            if (!string.IsNullOrEmpty(query.transfer_status)) {
                int value = int.Parse(query.transfer_status);
                filter = filter.And(c => c.Status == (TokenTransferStatus)value);
            }
            PagedResult<token_deposited_dto> result = new PagedResult<token_deposited_dto>();
            if (query.is_from_supplierpc) {
                result = context.TokenTransfer.FromCachePaged<TokenTransfer, token_deposited_dto>(query.page, query.size, filter,
                     orderBy => orderBy.OrderBy(c => SqlFunctions.CharIndex(((int)c.Status).ToString(), "0,3,1,2")).ThenByDescending(c => c.ApplyTime));
            } else {
                result = context.TokenTransfer.FromCachePaged<TokenTransfer, token_deposited_dto>(query.page, query.size, filter,
                    orderBy => orderBy.OrderByDescending(c => c.Status).ThenByDescending(c => c.ApplyTime));
            }

            return result;
        }
    }
}
